/*
 * Copyright (c) 2021 Huawei Device Co.,   Ltd.
 * Licensed under the Apache License,   Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,   software
 * distributed under the License is distributed on an "AS IS" BASIS,  
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,   either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "plugin_manager.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <string>
#include "hilog_wrapper.h"
#include "plugin_mpl.h"

namespace SwanLink {
namespace Finance {

PluginManager::PluginManager() {
    m_iStatus = ERR_PLUGIN_UNLOADED;

#ifdef  BUILD_WITH_ARM64
    m_cfgPath = "/system/lib64/plugin";
#else
    m_cfgPath = "/system/lib/plugin";
#endif
}

PluginManager::~PluginManager() {
    FreeAllPlugin();
}

bool PluginManager::LoadAllPlugin(const std::string& attr)
{
    struct dirent *dtp;
    DIR* dp;

    std::string current_path = m_cfgPath;  // + "/lib"+attr+"_*.z.so";
    std::string filter = "lib"+attr+"_";

    dp = opendir(current_path.c_str());

    if (dp == nullptr) {
        m_iStatus = ERR_PLUGIN_PATH_UNFIND;
        CARDSENDER_HILOGE(CARDSENDER_SRV, "Open %{public}s faild", current_path.c_str());
        return false;
    }

    while ((dtp = readdir(dp)) != nullptr) {
        if (strncmp(dtp->d_name, filter.c_str(), filter.length()) != 0)
            continue;
        std::shared_ptr<PluginMpl> plg = std::make_shared<PluginMpl>();
        if (!plg->LoadPlugin(m_cfgPath+"/"+dtp->d_name)) {
            CARDSENDER_HILOGE(CARDSENDER_SRV, "Load plugin %{public}s faild", dtp->d_name);
            continue;
        }
        m_listPlugins.push_back(plg);
    }

    // 关闭文件句柄
    closedir(dp);
    m_iStatus = SUCCESS;
    return true;
}

void PluginManager::FreeAllPlugin()
{
    m_listPlugins.clear();
    m_iStatus = ERR_PLUGIN_UNLOADED;
}

std::shared_ptr<IAdaptor> PluginManager::CreateAdaptor(const std::string& name)
{
    std::vector<std::shared_ptr<PluginMpl>>::const_iterator iter;
    for (iter = m_listPlugins.begin(); iter != m_listPlugins.end(); ++iter) {
        if ((*iter)->GetName() == name) {
            return (*iter)->CreateAdaptor();
        }
    }
    m_iStatus = ERR_PLUGIN_NOT_EXIST;
    return nullptr;
}

bool PluginManager::GetAccess(const std::string& name, ACCESS_MODE mode, const std::string& dev, DevAccess &access)
{
    std::vector<std::shared_ptr<PluginMpl>>::iterator iter;
    for (iter = m_listPlugins.begin(); iter != m_listPlugins.end(); ++iter) {
        if ((*iter)->GetName() == name) {
            return (*iter)->GetAccess(mode, dev.c_str(), access);
        }
    }
    m_iStatus = ERR_PLUGIN_NOT_EXIST;
    return false;
}

void PluginManager::DestroyAdaptor(int id, std::shared_ptr<IAdaptor>& adaptor)
{}

int  PluginManager::GetStatus(const std::string& name) const
{
    std::vector<std::shared_ptr<PluginMpl>>::const_iterator iter;
    for (iter = m_listPlugins.begin(); iter != m_listPlugins.end(); ++iter) {
        if ((*iter)->GetName() == name) {
            int status = (*iter)->GetStatus();
            if (status != SUCCESS)
                return status;
            break;
        }
    }
    return m_iStatus;
}
}  // namespace Finance
}  // namespace SwanLink
